﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Web;
using System.Web.Script.Serialization;
using System.Xml.Serialization;


namespace CrunchbaseGrabber
{
    public class CrunchBase
    {
        //this is the class definition to enum all of the data items to be retrieved from the
        //deserialized JSON object
        public string name;
        public string permaLink;
        public string homepage_url;
        public string crunchbase_url;
        public string category_code;
        public string description; // = "";
        public int? number_of_employees; // = 0;
        public string overview;
        public bool deadpool;
        public int? deadpool_year; //= "";
        public imgStructure image;
        public List<locStructure> offices;
        public string tag_list;
        public int? founded_year;
        public List<fndStructure> funding_rounds;
        public Dictionary<string, fndStructure> aggFundStructure = new Dictionary<string,fndStructure>();
        public List<string> keyword_tags;

        //helper function to generate the URL for the JSON object on a per company basis
        public void FixCrunchBaseURL()
        {
            string urlBase = "http://www.crunchbase.com/company/";

            crunchbase_url = urlBase + this.permaLink;
        }

        //helper function to generate the URL for the image to be pulled from the crunchbase API
        public string GetImageURL()
        {
            string baseURL = "http://www.crunchbase.com/";
            if (this.image != null)
            {
                return baseURL + this.image.available_sizes[1][1].ToString();
            }
            else
            {
                return "none";
            }
        }

        //simple function which pulls all the funding data for each company and aggregates the funding across
        //all rounds - the data is dumped into a dictionary that has all funding for each round
        public void AggregateFunding()
        {
            foreach (fndStructure fundingRound in this.funding_rounds)
            {
                if (this.aggFundStructure.ContainsKey(fundingRound.round_code))
                {
                    if (fundingRound.raised_amount == null)
                    {
                        fundingRound.raised_amount = 0;
                    }
                    
                    this.aggFundStructure[fundingRound.round_code].raised_amount += fundingRound.raised_amount;
                    

                    if (this.aggFundStructure[fundingRound.round_code].funded_year < fundingRound.funded_year)
                    {
                        this.aggFundStructure[fundingRound.round_code].funded_year = fundingRound.funded_year;
                    }
                }
                else
                {
                    if (fundingRound.raised_amount == null)
                    {
                        fundingRound.raised_amount = 0;
                    }

                    if (fundingRound.funded_year == null)
                    {
                        //use -1 to denote that the year returned was null
                        fundingRound.funded_year = -1;
                    }

                    this.aggFundStructure.Add(fundingRound.round_code, fundingRound);
                }
            }
        }

        //takes the dictionary and iterates through it to get the total funding.  Using the dictionary allows
        //for a pivot on funding round later should I choose
        public double GetAggregateFunding()
        {
            double totalFunding = 0;

            foreach (fndStructure fundingRound in this.funding_rounds)
            {
                totalFunding += (double)fundingRound.raised_amount;
            }

            return totalFunding;
        }

        //helper function to parse the keyword-tag string
        public void SplitTagString()
        {
            if (tag_list != null)
            {
                string[] keywordTags = tag_list.Split(',');

                foreach (string tag in keywordTags)
                {
                    //make sure those pesky trailing and leading spaces are gone
                    tag.Trim();
                }

                this.keyword_tags = keywordTags.ToList();
            }
        }

        //the number of keywords can be [0,n), which makes for challenges with the Pivot data creation.  To simplify
        //this, I simply take 5 keywords if there are 5, and if not, return \t in place of a word
        //the special case is a null, and to avoid a bug in the Pivot CXML, return "none" for the first word, and 4x\t
        public string GetKeywordList()
        {
            string tmpString = "";
            if (keyword_tags != null)
            {
                for (int i = 0; i < 5; i++)
                {
                    if (i < keyword_tags.Count())
                    {
                        tmpString += keyword_tags[i].ToString() + "\t";
                    }
                    else
                    {
                        tmpString += " " + "\t";
                    }
                }
            }
            else
            {
                tmpString = "none\t\t\t\t\t";
            }

            return tmpString;
        }

        public CrunchBase()
        {
        }
    }

    //class for the JSON data about logos
    public class imgStructure
    {
        public List<List<object>> available_sizes;
        public string attribution;
    }

    //class for the JSON data about funding
    public class fndStructure
    {
        public string round_code;
        public double? raised_amount;
        public int? funded_year;
    }

    //class for the JSON data about the company office location
    public class locStructure
    {
        public string city;
        public string state_code;
        public string country_code;
    }

    //class to create the JSON stream, fetch it
    public class CrunchJsonStream
    {
        public string cbJsonStream;
        
        public string GetJsonStream(string companyName)
        {
            string jsonStream;
            string apiUrlBase = "http://api.crunchbase.com/v/1/company/";
            string urlEnd = ".js";

            WebRequest wrGetURL;
            wrGetURL = WebRequest.Create(apiUrlBase + companyName + urlEnd);

            try
            {
                jsonStream = new StreamReader(wrGetURL.GetResponse().GetResponseStream()).ReadToEnd();
                return jsonStream;
            }
            catch (System.Net.WebException e)
            {
                Console.WriteLine("Company: {0} - URL bad", companyName);
            }
            catch (Exception e)
            {
                Console.WriteLine("Generic Exception Caught: {0}", e.ToString());
            }

            //Console.WriteLine("Done getting JSON");
            return jsonStream=null;
        }
    }
}
